//! Player 测试

use std::{sync::Arc, time::Duration};

use indicatif::{ProgressBar, ProgressStyle};
use rfd::AsyncFileDialog;
use serde_json::Value;
use tokio::sync::Mutex;

use crate::{mapper::create_mapper, player::MidiPlayer};

use super::async_block_test;

/// 打印 MIDI 文件的时长
#[test]
fn print_duration() {
    async_block_test(async {
        // 选取 MIDI 文件
        println!("请选择一个 Midi 文件");
        let file = AsyncFileDialog::new()
            .add_filter("Midi 文件", &["mid", "midi"])
            .pick_file()
            .await
            .unwrap();

        // 读取 MIDI 文件
        let path = file.path().to_str().unwrap();
        let bytes = file.read().await;
        let player = MidiPlayer::from_bytes(bytes).unwrap();

        // 获取 Midi 时长
        let duration = player.duration().await;
        let total_secs = duration.as_secs_f64().round() as u64;
        let secs = total_secs % 60;
        let mins = total_secs / 60;

        // 打印结果
        println!("Midi 文件 “{path}” 的时长为 {mins}分{secs}秒");
    });
}

/// Midi 播放测试
#[test]
fn play_midi() {
    async_block_test(async {
        // 选取 MIDI 文件 和 Mapper 配置文件
        println!("请选择一个 Midi 文件 和 一个 Mapper 配置文件");
        let (midi_file, mapper_file) = tokio::join!(
            AsyncFileDialog::new()
                .add_filter("Midi 文件", &["mid", "midi"])
                .pick_file(),
            AsyncFileDialog::new()
                .add_filter("映射器配置文件", &["json"])
                .pick_file(),
        );
        let (midi_file, mapper_file) = (midi_file.unwrap(), mapper_file.unwrap());

        // 读取文件
        let player = MidiPlayer::from_bytes(midi_file.read().await).unwrap();
        let value: Value =
            serde_json::from_str(&String::from_utf8(mapper_file.read().await).unwrap()).unwrap();

        // 构造 Mapper
        let mapper = create_mapper(value["name"].as_str().unwrap(), value["rule"].clone()).unwrap();

        // 获取播放时长
        let duration = player.duration().await;
        let duration_secs = duration.as_secs_f64().round() as u64;
        let duration_str = format!(
            "{:0>2}:{:0>2}:{:0>2}",
            duration_secs / 3600,
            (duration_secs % 3600) / 60,
            duration_secs % 60
        );

        // 初始化播放进度条
        let midi_file_name = midi_file.path().file_name().unwrap().to_str().unwrap();
        let bar = ProgressBar::new(duration.as_millis() as u64);
        bar.set_style(
            ProgressStyle::default_bar()
                .template(&format!(
                    "{{spinner:.green}} {{elapsed_precise}} {{wide_bar:.cyan/blue}} {duration_str}"
                ))
                .unwrap(),
        );

        // 播放进度变化
        let progress_task = async {
            bar.tick();
            while bar.elapsed() < duration {
                bar.set_position(bar.elapsed().as_millis() as u64);

                // 1 秒 最多 10 次刷新
                tokio::time::sleep(Duration::from_millis(100)).await;
            }

            bar.finish();
            println!("{} 播放完毕", midi_file_name)
        };

        // 播放 Midi 并 显示进度
        tokio::join!(
            player.play(Arc::new(Mutex::new(mapper)), None, None),
            progress_task
        );
    });
}
